package com.loukou.lkt.company.service.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import com.loukou.lkt.cache.CompanyCache;
import com.loukou.lkt.company.dao.CompanyDao;
import com.loukou.lkt.company.dao.UserDao;
import com.loukou.lkt.company.entity.Company;
import com.loukou.lkt.company.entity.CompanyDatabase;
import com.loukou.lkt.company.entity.User;
import com.loukou.lkt.company.service.UserService;
import com.loukou.lkt.lkt.dao.PrivilegeDao;
import com.loukou.lkt.lkt.dao.RoleDao;
import com.loukou.lkt.lkt.dao.RolePrivilegeDao;
import com.loukou.lkt.lkt.dao.UserRoleDao;
import com.loukou.lkt.lkt.entity.Privilege;
import com.loukou.lkt.lkt.entity.Role;
import com.loukou.lkt.lkt.entity.RolePrivilege;
import com.loukou.lkt.lkt.entity.UserRole;
import com.loukou.lkt.lkt.req.SearchUserReq;
import com.loukou.lkt.lkt.resp.AuthInfo;
import com.loukou.lkt.lkt.resp.DataGrid;
import com.loukou.lkt.lkt.resp.RespDto;
import com.loukou.lkt.lkt.resp.UserResp;
import com.loukou.lkt.lkt.utils.MD5;

@Service
public class UserServiceImpl implements UserService{
	
	@Autowired
	private UserDao userDao;
	
	@Autowired
	private RoleDao roleDao;
	
	@Autowired
	private PrivilegeDao privilegeDao;
	
	@Autowired
	private UserRoleDao userRoleDao;
	
	@Autowired
	private RolePrivilegeDao rolePrivilegeDao;
	
	@Autowired
	private CompanyDao companyDao;
	
	@Autowired
	private CompanyCache companyCache;
	
	private CompanyDatabase getCompanyDatabase(int companyId){
		List<CompanyDatabase> cdb = companyCache.getCompanyDatabaseMap().get(companyId);
		if(CollectionUtils.isEmpty(cdb)){
			return null;
		}
		
		return cdb.get(0);
	}
	
	@Override
	public AuthInfo getAuthInfo(String username, String password) {
		String pwd = MD5.GetMD5Code(password);
		User userDto = userDao.findByUsernameAndPassword(username, pwd);
		if(userDto != null){
			AuthInfo authInfo = new AuthInfo();
			authInfo.setId(userDto.getId());
			authInfo.setUsername(userDto.getUsername());
			authInfo.setRealName(userDto.getRealName());
			Company company = companyDao.findOne(userDto.getCompanyId());
			if(company!=null){
				authInfo.setCompany(company);
				CompanyDatabase companyDatabase = getCompanyDatabase(company.getId());
				if(companyDatabase!=null){
					authInfo.setCompanyDatabaseId(companyDatabase.getId());
				}
			}
			List<UserRole> userRoleList = userRoleDao.findByUserId(userDto.getId());
			List<Integer> roleIdList = new ArrayList<Integer>();
			for(UserRole userRole: userRoleList){
				if(!roleIdList.contains(userRole.getRoleId())){
					roleIdList.add(userRole.getRoleId());
				}
			}
			List<String> roleKeyList = new ArrayList<String>();
			//获取该用户的所有角色标识
			if(roleIdList.size() > 0){
				List<Role>  roleList = roleDao.findByIdIn(roleIdList);
				for(Role role: roleList){
					roleKeyList.add(role.getRoleKey());
				}
				authInfo.setRoles(roleKeyList);
				List<RolePrivilege> rolePriList = rolePrivilegeDao.findByRoleIdIn(roleIdList);
				List<Integer> priIdList = new ArrayList<Integer>();
				//获取该用户的所有权限标识
				for(RolePrivilege rolePri : rolePriList){
					if(!priIdList.contains(rolePri)){
						priIdList.add(rolePri.getPriId());
					}
				}
				if(priIdList.size()>0){
					List<Privilege> priList = privilegeDao.findByIdIn(priIdList);
					List<String> priKeyList = new ArrayList<String>();
					for(Privilege pri: priList){
						if(!priKeyList.contains(pri.getPriKey())){
							priKeyList.add(pri.getPriKey());
						}
					}
					authInfo.setPrivileges(priKeyList);
				}
			}
			return authInfo;
		}
		return null;
	}

	@Override
	public List<Role> getAllRole() {
		List<Role> roleList = (List<Role>) roleDao.findAll();
		return roleList;
	}

	@Override
	public List<Privilege> getAllPrivileges() {
		List<Privilege> privilegeList = (List<Privilege>) privilegeDao.findAll();
		return privilegeList;
	}

	@Override
	public DataGrid queryUserPage(SearchUserReq userReq) {
		DataGrid dataGrid = new DataGrid();
		int pageSize = userReq.getLimit()==0?10:userReq.getLimit();
		int pageNum = userReq.getOffset()/pageSize;
		Sort pageSort = new Sort(Sort.Direction.ASC, "id");
		Pageable pageable = new PageRequest(pageNum, pageSize, pageSort);
		List<Integer> roleIds = new ArrayList<Integer>();
		if(userReq.getPrivilegeId() > 0){
			List<RolePrivilege> rolePrivilegeList = rolePrivilegeDao.findByPriId(userReq.getPrivilegeId());
			if(rolePrivilegeList == null || rolePrivilegeList.size() == 0){
				return dataGrid;
			}
			for(RolePrivilege role: rolePrivilegeList){
				if(!roleIds.contains(role.getRoleId())){
					roleIds.add(role.getRoleId());
				}
			}
		}
		if(userReq.getRoleId()>0){
			if(roleIds.size() >0 &&!roleIds.contains(userReq.getRoleId())){
				return dataGrid;
			}
			roleIds.clear();
			roleIds.add(userReq.getRoleId());
		}
		List<Integer> userIds = new ArrayList<Integer>();
		if(roleIds.size()>0){
			List<UserRole> userRoleList = userRoleDao.findByRoleIdIn(roleIds);
			if(userRoleList == null || userRoleList.size() == 0){
				return dataGrid;
			}
			for(UserRole userRole: userRoleList){
				if(!userIds.contains(userRole.getUserId())){
					userIds.add(userRole.getUserId());
				}
			}
		}
		Page<User> userPage = null;
		if(userIds.size()>0){
			if(StringUtils.isNotBlank(userReq.getRealname())){
				userPage = userDao.findByRealNameAndIdIn(userReq.getRealname(), userIds, pageable);
			}else{
				userPage = userDao.findByIdIn(userIds, pageable);
			}
		}else{
			if(StringUtils.isNotBlank(userReq.getRealname())){
				userPage = userDao.findByRealName(userReq.getRealname(), pageable);
			}else{
				userPage = userDao.findAll(pageable);
			}
		}
		if(userPage == null){
			return dataGrid;
		}
		List<User> userList = userPage.getContent();
		if(userList == null || userList.size() == 0){
			return dataGrid;
		}
		userIds.clear();
		for(User user: userList){
			userIds.add(user.getId());
		}
		List<UserRole> userRoleList = userRoleDao.findByUserIdIn(userIds);
		Map<Integer, List<Integer>> userRoleIdListMap = new HashMap<Integer, List<Integer>>();
		List<Role> allRoles = (List<Role>) roleDao.findAll();
		Map<Integer, Role> roleMap = new HashMap<Integer, Role>();
		for(Role role: allRoles){
			roleMap.put(role.getId(), role);
		}
		for(UserRole userRole: userRoleList){
			List<Integer> userRoleIdList = userRoleIdListMap.get(userRole.getUserId());
			if(userRoleIdList == null){
				userRoleIdList = new ArrayList<Integer>();
				userRoleIdListMap.put(userRole.getUserId(), userRoleIdList);
			}
			if(!userRoleIdList.contains(userRole.getRoleId())){
				userRoleIdList.add(userRole.getRoleId());
			}
		}
		Map<Integer, List<String>> rolePriKeyMap = getRolePriKeyMap();
		List<UserResp> userRespList = new ArrayList<UserResp>();
		for(User user: userList){
			UserResp userResp = new UserResp();
			userResp.setId(user.getId());
			userResp.setRealname(user.getRealName());
			userResp.setUsername(user.getUsername());
			String roleNames = "";
			String priKeys = "";
			List<String> priKeyList = new ArrayList<String>();
			List<Integer> roleIdList = userRoleIdListMap.get(user.getId());
			if(roleIdList != null && roleIdList.size()>0){
				for(Integer roleId: roleIdList){
					Role r = roleMap.get(roleId);
					if(r != null){
						roleNames += ","+r.getRoleName();
						List<String> rolePriKeys = rolePriKeyMap.get(roleId);
						if(rolePriKeys != null && rolePriKeys.size()>0){
							for(String priKey : rolePriKeys){
								if(!priKeyList.contains(priKey)){
									priKeyList.add(priKey);
								}
							}
						}
					}
				}
			}
			if(StringUtils.isNotBlank(roleNames)){
				roleNames = roleNames.substring(1);
			}
			for(String priKey: priKeyList){
				priKeys += ","+priKey;
			}
			if(StringUtils.isNotBlank(priKeys)){
				priKeys = priKeys.substring(1);
			}
			userResp.setPrivileges(priKeys);
			userResp.setRoles(roleNames);
			userRespList.add(userResp);
		}
		dataGrid.setTotal(userPage.getTotalElements());
		dataGrid.setRows(userRespList);
		return dataGrid;
	}
	
	private Map<Integer, List<String>> getRolePriKeyMap(){
		Map<Integer, List<String>> rolePriKeyMap = new HashMap<Integer, List<String>>();
		List<RolePrivilege> rolePriList = (List<RolePrivilege>) rolePrivilegeDao.findAll();
		List<Privilege> priList = (List<Privilege>) privilegeDao.findAll();
		Map<Integer, String> priKeyMap = new HashMap<Integer, String>();
		for(Privilege pri: priList){
			priKeyMap.put(pri.getId(), pri.getPriKey());
		}
		for(RolePrivilege rolePri: rolePriList){
			List<String> priKeyList = rolePriKeyMap.get(rolePri.getRoleId());
			if(priKeyList == null){
				priKeyList = new ArrayList<String>();
				rolePriKeyMap.put(rolePri.getRoleId(), priKeyList);
			}
			String priKey = priKeyMap.get(rolePri.getPriId());
			if(StringUtils.isNotBlank(priKey) && !priKeyList.contains(priKey)){
				priKeyList.add(priKey);
			}
		}
		return rolePriKeyMap;
	}

	@Override
	public void deleteUser(int id) {
		User user = userDao.findOne(id);
		if(user != null){
			userDao.delete(user);
		}
		List<UserRole> userRoleList = userRoleDao.findByUserId(id);
		if(userRoleList != null){
			for(UserRole userRole: userRoleList){
				userRoleDao.delete(userRole);
			}
		}
	}

	@Override
	public UserResp getUserResp(int id) {
		User user = userDao.findOne(id);
		List<UserRole> userRoleList = userRoleDao.findByUserId(id);
		UserResp userResp = new UserResp();
		userResp.setId(user.getId());
		userResp.setRealname(user.getRealName());
		userResp.setUsername(user.getUsername());
		List<Integer> roleIdList = new ArrayList<Integer>();
		if(userRoleList != null && userRoleList.size() > 0){
			for(UserRole userRole: userRoleList){
				if(!roleIdList.contains(userRole.getRoleId())){
					roleIdList.add(userRole.getRoleId());
				}
			}
		}
		if(roleIdList.size() > 0){
			List<Role> roleList = roleDao.findByIdIn(roleIdList);
			userResp.setRoleList(roleList);
		}
		return userResp;
	}

	@Override
	public void deleteUserRole(int userId, int roleId) {
		UserRole userRole = userRoleDao.findByUserIdAndRoleId(userId, roleId);
		userRoleDao.delete(userRole);
		
	}

	@Override
	public RespDto<Role> addUserRole(int userId, int roleId) {
		UserRole userRole = userRoleDao.findByUserIdAndRoleId(userId, roleId);
		RespDto<Role> resp = new RespDto<Role> ();
		if(userRole != null){
			resp.setCode(202);
			resp.setMsg("用户角色已存在");
		}else{
			userRole = new UserRole();
			userRole.setRoleId(roleId);
			userRole.setUserId(userId);
			userRoleDao.save(userRole);
			Role role = roleDao.findOne(roleId);
			resp.setCode(200);
			resp.setResult(role);
		}
		return resp;
	}

	@Override
	public RespDto<String> addUser(String realname, String username, int[] roleIds) {
		RespDto<String> resp = new RespDto<String>();
		User oldUser = userDao.findByUsername(username);
		if(oldUser != null){
			resp.setCode(405);
			resp.setResult("用户名已存在");
			return resp;
			
		}
		User user = new User();
		user.setRealName(realname);
		user.setUsername(username);
		user.setPassword(MD5.GetMD5Code(username));
		userDao.save(user);
		deleteUserRolesByUserId(user.getId());
		if(roleIds!= null && roleIds.length>0){
			for(Integer roleId: roleIds){
				UserRole userRole = new UserRole();
				userRole.setRoleId(roleId);
				userRole.setUserId(user.getId());
				userRoleDao.save(userRole);
			}
		}
		return resp;
	}
	
	private void deleteUserRolesByUserId(Integer userId){
		List<UserRole> userRoleList = userRoleDao.findByUserId(userId);
		if(userRoleList !=null && userRoleList.size()>0){
			for(UserRole userRole: userRoleList){
				userRoleDao.delete(userRole);
			}
		}
	}

	@Override
	public RespDto<String> editUser(int userId, String realname, String username, int[] roleIds) {
		RespDto<String> resp = new RespDto<String>();
		if(userId >0){
			User oldUser = userDao.findByUsernameAndIdNot(username, userId);
			if(oldUser != null){
				resp.setCode(405);
				resp.setResult("账户已存在");
				return resp;
			}
			userDao.updateUser(realname, username, userId);
			deleteUserRolesByUserId(userId);
			if(roleIds!= null && roleIds.length>0){
				for(Integer roleId: roleIds){
					UserRole userRole = new UserRole();
					userRole.setRoleId(roleId);
					userRole.setUserId(userId);
					userRoleDao.save(userRole);
				}
			}
		}
		return resp;
	}  
}
